#include "heros.hh"

namespace heros
{
    highwayman::highwayman(std::string hero_name, unsigned position_inteam) {
        this->skill1_targets = hero_settings::Highwayman::skill::Wicked_Slice::Target;
        this->skill2_targets = hero_settings::Highwayman::skill::Point_Blank_Shot::Target;
        this->name = hero_name;
        this->description = hero_settings::Highwayman::description;
        this->is_dead = false;
        this->is_dying = false;
        this->maxHealth = hero_settings::Highwayman::maxHealth;
        this->health = this->maxHealth;
        this->min_attack = hero_settings::Highwayman::min_attack;
        this->max_attack = hero_settings::Highwayman::max_attack;
        this->speed = hero_settings::Highwayman::speed;
        this->round_speed = this->speed;
        this->position_inteam = position_inteam;
        this->stress = 0;
        this->round_finsh = false;
        this->skill1_description = hero_settings::Highwayman::skill::Wicked_Slice::description;
        this->skill2_description = hero_settings::Highwayman::skill::Point_Blank_Shot::description;
        this->skill1_name = hero_settings::Highwayman::skill::Wicked_Slice::name;
        this->skill2_name = hero_settings::Highwayman::skill::Point_Blank_Shot::name;
        this->crit = hero_settings::Highwayman::crit;
        this->blight = hero_settings::Highwayman::blight;
        this->bleed = hero_settings::Highwayman::bleed;
        this->stun = hero_settings::Highwayman::stun;
        this->deathBlow = hero_settings::Highwayman::deathBlow;
        this->trap = hero_settings::Highwayman::trap;
        this->dodge = hero_settings::Highwayman::dodge;
    }

    highwayman::~highwayman() {
        
    }

    heros::highwayman::highwayman(const highwayman& other) :
        Ahero(other) 
    {}

    heros::highwayman& heros::highwayman::operator=(const highwayman& other) {
        if (this != &other) {
            Ahero::operator=(other);
        }
        return *this;
    }

    void highwayman::skill1(std::vector<ICharacter*>& team, std::vector<ICharacter*>& other_team, unsigned target_pos) {
        if (target_pos >= team.size()) {
            std::cout << "The air in position " << std::to_string(target_pos + 1) << " get hurt...\n";
        } else {
            std::cout << this->name << " use " << this->skill1_name << " to " << team[target_pos]->getName();
            if (target_pos > team.size() - 1 || randomFunc::get_persent_bool(team[target_pos]->getDodge())) {
                std::cout << "\nMiss!\n";
            } else {
                unsigned damage = randomFunc::get_Random_Num(this->min_attack, this->max_attack) * hero_settings::Highwayman::skill::Wicked_Slice::damage_times;
                if (randomFunc::get_persent_bool(this->crit) + hero_settings::Highwayman::skill::Wicked_Slice::self_crit)
                {
                    damage *= 1.5;
                    std::cout << "\nCrit!\n";
                    this->stressHealing(5);
                    std::cout << this->getName() << "'s stress decreased 5.\n";
                }
                team[target_pos]->takeDamage(damage);
                std::cout << "\n" << this->name << " damage " << team[target_pos]->getName() << " " << std::to_string(damage) << "\n";
                // if (randomFunc::get_persent_bool(140 - team[target_pos].getBleed())) {
                //     buff_and_effect::bleed bleed(1, 1, team[target_pos]);
                //     team[target_pos].takeBuff(bleed);
                //     std::cout << team[target_pos].getName() << " get a bled buff " << bleed.samllInfo() << "\n";
                // }
            }  
        }
    }
    
    void highwayman::skill2(std::vector<ICharacter*>& team, std::vector<ICharacter*>& other_team, unsigned target_pos) {
        if (target_pos >= team.size()) {
            std::cout << "The air in position " << std::to_string(target_pos + 1) << " get hurt...\n";
        } else {
            std::cout << this->name << " use " << this->skill2_name << " to " << team[target_pos]->getName();
            if (target_pos > team.size() - 1 || randomFunc::get_persent_bool(team[target_pos]->getDodge())) {
                std::cout << "\nMiss!\n";
            } else {
                unsigned damage = randomFunc::get_Random_Num(this->min_attack, this->max_attack) * hero_settings::Highwayman::skill::Point_Blank_Shot::damage_times;
                if (randomFunc::get_persent_bool(this->crit + hero_settings::Highwayman::skill::Point_Blank_Shot::self_crit))
                {
                    damage *= 1.5;
                    std::cout << "\nCrit!\n";
                    this->stressHealing(5);
                    std::cout << this->getName() << "'s stress decreased 5.\n";
                }
                team[target_pos]->takeDamage(damage);
                std::cout << "\n" << this->name << " damage " << team[target_pos]->getName() << " " << std::to_string(damage) << "\n";
                // if (randomFunc::get_persent_bool(140 - team[target_pos].getStun())) {
                //     buff_and_effect::stun stun(team[target_pos]);
                //     team[target_pos].takeBuff(stun);
                //     std::cout << team[target_pos].getName() << " get a stun buff " << stun.samllInfo() << "\n";
                // }
            }  
        }
    }

    Jester::Jester(std::string hero_name, unsigned position_inteam) {
        this->skill1_targets = hero_settings::Jester::skill::Inspiring_Tune::Target;
        this->skill2_targets = hero_settings::Jester::skill::Dirk_Stab::Target;
        this->name = hero_name;
        this->description = hero_settings::Jester::description;
        this->is_dead = false;
        this->is_dying = false;
        this->maxHealth = hero_settings::Jester::maxHealth;
        this->health = this->maxHealth;
        this->min_attack = hero_settings::Jester::min_attack;
        this->max_attack = hero_settings::Jester::max_attack;
        this->speed = hero_settings::Jester::speed;
        this->round_speed = this->speed;
        this->position_inteam = position_inteam;
        this->stress = 0;
        this->round_finsh = false;
        this->skill1_description = hero_settings::Jester::skill::Inspiring_Tune::description;
        this->skill2_description = hero_settings::Jester::skill::Dirk_Stab::description;
        this->skill1_name = hero_settings::Jester::skill::Inspiring_Tune::name;
        this->skill2_name = hero_settings::Jester::skill::Dirk_Stab::name;
        this->crit = hero_settings::Jester::crit;
        this->blight = hero_settings::Jester::blight;
        this->bleed = hero_settings::Jester::bleed;
        this->stun = hero_settings::Jester::stun;
        this->deathBlow = hero_settings::Jester::deathBlow;
        this->trap = hero_settings::Jester::trap;
        this->dodge = hero_settings::Jester::dodge;
    }

    Jester::~Jester() {
        
    }

    heros::Jester::Jester(const Jester& other) :
        Ahero(other) 
    {}

    heros::Jester& heros::Jester::operator=(const Jester& other) {
        if (this != &other) {
            Ahero::operator=(other);
        }
        return *this;
    }

    void Jester::skill1(std::vector<ICharacter*>& team, std::vector<ICharacter*>& other_team, unsigned target_pos) {
        if (target_pos >= other_team.size()) {
            std::cout << "The air in position " << std::to_string(target_pos + 1) << " get hurt...\n";
        } else {
            std::cout << this->name << " use " << this->skill1_name << " to " << other_team[target_pos]->getName();
            unsigned damage = hero_settings::Jester::skill::Inspiring_Tune::Stress_healing;
            if (randomFunc::get_persent_bool(this->crit))
            {
                damage *= 1.5;
                std::cout << "\nCrit!\n";
                this->stressHealing(5);
                std::cout << this->getName() << "'s stress decreased 5.\n";
            }
            if (auto* h = dynamic_cast<Ahero*>(other_team[target_pos])) {
                h->stressHealing(damage);
                std::cout << "\n" << this->name << " reduce " << other_team[target_pos]->getName() << "'s stress " << std::to_string(damage) << "\n";
            }
                // if (randomFunc::get_persent_bool(140 - team[target_pos].getBleed())) {
                //     buff_and_effect::bleed bleed(1, 1, team[target_pos]);
                //     team[target_pos].takeBuff(bleed);
                //     std::cout << team[target_pos].getName() << " get a bled buff " << bleed.samllInfo() << "\n";
                // }
            
        }
    }

    void Jester::skill2(std::vector<ICharacter*>& team, std::vector<ICharacter*>& other_team, unsigned target_pos) {
        if (target_pos >= team.size()) {
            std::cout << "The air in position " << std::to_string(target_pos + 1) << " get hurt...\n";
        } else {
            std::cout << this->name << " use " << this->skill2_name << " to " << team[target_pos]->getName();
            if (target_pos > team.size() - 1 || randomFunc::get_persent_bool(team[target_pos]->getDodge())) {
                std::cout << "\nMiss!\n";
            } else {
                unsigned damage = randomFunc::get_Random_Num(this->min_attack, this->max_attack) * hero_settings::Jester::skill::Dirk_Stab::damage_times;
                if (randomFunc::get_persent_bool(this->crit + hero_settings::Jester::skill::Dirk_Stab::self_crit))
                {
                    damage *= 1.5;
                    std::cout << "\nCrit!\n";
                    this->stressHealing(5);
                    std::cout << this->getName() << "'s stress decreased 5.\n";
                }
                team[target_pos]->takeDamage(damage);
                std::cout << "\n" << this->name << " damage " << team[target_pos]->getName() << " " << std::to_string(damage) << "\n";
                // if (randomFunc::get_persent_bool(140 - team[target_pos].getStun())) {
                //     buff_and_effect::stun stun(team[target_pos]);
                //     team[target_pos].takeBuff(stun);
                //     std::cout << team[target_pos].getName() << " get a stun buff " << stun.samllInfo() << "\n";
                // }
            }  
        }
    }

    Crusader::Crusader(std::string hero_name, unsigned position_inteam) {
        this->skill1_targets = hero_settings::Crusader::skill::Inspiring_Cry::Target;
        this->skill2_targets = hero_settings::Crusader::skill::Smite::Target;
        this->name = hero_name;
        this->description = hero_settings::Crusader::description;
        this->is_dead = false;
        this->is_dying = false;
        this->maxHealth = hero_settings::Crusader::maxHealth;
        this->health = this->maxHealth;
        this->min_attack = hero_settings::Crusader::min_attack;
        this->max_attack = hero_settings::Crusader::max_attack;
        this->speed = hero_settings::Crusader::speed;
        this->round_speed = this->speed;
        this->position_inteam = position_inteam;
        this->stress = 0;
        this->round_finsh = false;
        this->skill1_description = hero_settings::Crusader::skill::Inspiring_Cry::description;
        this->skill2_description = hero_settings::Crusader::skill::Smite::description;
        this->skill1_name = hero_settings::Crusader::skill::Inspiring_Cry::name;
        this->skill2_name = hero_settings::Crusader::skill::Smite::name;
        this->crit = hero_settings::Crusader::crit;
        this->blight = hero_settings::Crusader::blight;
        this->bleed = hero_settings::Crusader::bleed;
        this->stun = hero_settings::Crusader::stun;
        this->deathBlow = hero_settings::Crusader::deathBlow;
        this->trap = hero_settings::Crusader::trap;
        this->dodge = hero_settings::Crusader::dodge;
    }

    Crusader::~Crusader() {
        
    }

    heros::Crusader::Crusader(const Crusader& other) :
        Ahero(other) 
    {}

    heros::Crusader& heros::Crusader::operator=(const Crusader& other) {
        if (this != &other) {
            Ahero::operator=(other);
        }
        return *this;
    }

    void Crusader::skill1(std::vector<ICharacter*>& team, std::vector<ICharacter*>& other_team, unsigned target_pos) {
        if (target_pos >= other_team.size()) {
            std::cout << "The air in position " << std::to_string(target_pos + 1) << " get hurt...\n";
        } else {
            std::cout << this->name << " use " << this->skill1_name << " to " << other_team[target_pos]->getName();
            unsigned damage = hero_settings::Crusader::skill::Inspiring_Cry::Stress_healing;
            if (randomFunc::get_persent_bool(this->crit))
            {
                damage *= 1.5;
                std::cout << "\nCrit!\n";
                this->stressHealing(5);
                std::cout << this->getName() << "'s stress decreased 5.\n";
            }
            if (auto* h = dynamic_cast<Ahero*>(other_team[target_pos])) {
                h->stressHealing(damage);
            }
            std::cout << "\n" << this->name << " reduce " << other_team[target_pos]->getName() << "'s stress " << std::to_string(damage) << "\n";
                // if (randomFunc::get_persent_bool(140 - team[target_pos].getBleed())) {
                //     buff_and_effect::bleed bleed(1, 1, team[target_pos]);
                //     team[target_pos].takeBuff(bleed);
                //     std::cout << team[target_pos].getName() << " get a bled buff " << bleed.samllInfo() << "\n";
                // }
            
        }
    }

    void Crusader::skill2(std::vector<ICharacter*>& team, std::vector<ICharacter*>& other_team, unsigned target_pos) {
        if (target_pos >= team.size()) {
            std::cout << "The air in position " << std::to_string(target_pos + 1) << " get hurt...\n";
        } else {
            std::cout << this->name << " use " << this->skill2_name << " to " << team[target_pos]->getName();
            if (target_pos > team.size() - 1 || randomFunc::get_persent_bool(team[target_pos]->getDodge())) {
                std::cout << "\nMiss!\n";
            } else {
                unsigned damage = randomFunc::get_Random_Num(this->min_attack, this->max_attack) * hero_settings::Crusader::skill::Smite::damage_times;
                if (randomFunc::get_persent_bool(this->crit + hero_settings::Crusader::skill::Smite::self_crit))
                {
                    damage *= 1.5;
                    std::cout << "\nCrit!\n";
                    this->stressHealing(5);
                    std::cout << this->getName() << "'s stress decreased 5.\n";
                }
                team[target_pos]->takeDamage(damage);
                std::cout << "\n" << this->name << " damage " << team[target_pos]->getName() << " " << std::to_string(damage) << "\n";
                // if (randomFunc::get_persent_bool(140 - team[target_pos].getStun())) {
                //     buff_and_effect::stun stun(team[target_pos]);
                //     team[target_pos].takeBuff(stun);
                //     std::cout << team[target_pos].getName() << " get a stun buff " << stun.samllInfo() << "\n";
                // }
            }  
        }
    }

    Houndmaster::Houndmaster(std::string hero_name, unsigned position_inteam) {
        this->skill1_targets = hero_settings::Houndmaster::skill::Cry_Havoc::Target;
        this->skill2_targets = hero_settings::Houndmaster::skill::Hound_Rush::Target;
        this->name = hero_name;
        this->description = hero_settings::Houndmaster::description;
        this->is_dead = false;
        this->is_dying = false;
        this->maxHealth = hero_settings::Houndmaster::maxHealth;
        this->health = this->maxHealth;
        this->min_attack = hero_settings::Houndmaster::min_attack;
        this->max_attack = hero_settings::Houndmaster::max_attack;
        this->speed = hero_settings::Houndmaster::speed;
        this->round_speed = this->speed;
        this->position_inteam = position_inteam;
        this->stress = 0;
        this->round_finsh = false;
        this->skill1_description = hero_settings::Houndmaster::skill::Cry_Havoc::description;
        this->skill2_description = hero_settings::Houndmaster::skill::Hound_Rush::description;
        this->skill1_name = hero_settings::Houndmaster::skill::Cry_Havoc::name;
        this->skill2_name = hero_settings::Houndmaster::skill::Hound_Rush::name;
        this->crit = hero_settings::Houndmaster::crit;
        this->blight = hero_settings::Houndmaster::blight;
        this->bleed = hero_settings::Houndmaster::bleed;
        this->stun = hero_settings::Houndmaster::stun;
        this->deathBlow = hero_settings::Houndmaster::deathBlow;
        this->trap = hero_settings::Houndmaster::trap;
        this->dodge = hero_settings::Houndmaster::dodge;
    }

    Houndmaster::~Houndmaster() {
        
    }

    heros::Houndmaster::Houndmaster(const Houndmaster& other) :
        Ahero(other) 
    {}

    heros::Houndmaster& heros::Houndmaster::operator=(const Houndmaster& other) {
        if (this != &other) {
            Ahero::operator=(other);
        }
        return *this;
    }

    void Houndmaster::skill1(std::vector<ICharacter*>& team, std::vector<ICharacter*>& other_team, unsigned target_pos) {
        if (target_pos >= other_team.size()) {
            std::cout << "The air in position " << std::to_string(target_pos + 1) << " get hurt...\n";
        } else {
            std::cout << this->name << " use " << this->skill1_name << "\n";
            unsigned damage = hero_settings::Houndmaster::skill::Cry_Havoc::Stress_healing;
            if (randomFunc::get_persent_bool(this->crit))
            {
                damage *= 1.5;
                std::cout << "\nCrit!\n";
                this->stressHealing(5);
                std::cout << this->getName() << "'s stress decreased 5.\n";
            }
            
            for (auto* obj : other_team) {
                if (auto* h = dynamic_cast<Ahero*>(obj)) {
                    if (randomFunc::get_persent_bool(hero_settings::Houndmaster::skill::Cry_Havoc::stress_present)) {
                        h->stressHealing(damage);
                        std::cout << "\n" << this->name << " reduce " << h->getName() << "'s stress " << std::to_string(damage) << "\n";
                    }
                }
                // if (randomFunc::get_persent_bool(140 - team[target_pos].getBleed())) {
                //     buff_and_effect::bleed bleed(1, 1, team[target_pos]);
                //     team[target_pos].takeBuff(bleed);
                //     std::cout << team[target_pos].getName() << " get a bled buff " << bleed.samllInfo() << "\n";
                // }
            }
        }
    }

    void Houndmaster::skill2(std::vector<ICharacter*>& team, std::vector<ICharacter*>& other_team, unsigned target_pos) {
        if (target_pos >= team.size()) {
            std::cout << "The air in position " << std::to_string(target_pos + 1) << " get hurt...\n";
        } else {
            std::cout << this->name << " use " << this->skill2_name << " to " << team[target_pos]->getName();
            if (target_pos > team.size() - 1 || randomFunc::get_persent_bool(team[target_pos]->getDodge())) {
                std::cout << "\nMiss!\n";
            } else {
                unsigned damage = randomFunc::get_Random_Num(this->min_attack, this->max_attack) * hero_settings::Houndmaster::skill::Hound_Rush::damage_times;
                if (randomFunc::get_persent_bool(this->crit + hero_settings::Houndmaster::skill::Hound_Rush::self_crit))
                {
                    damage *= 1.5;
                    std::cout << "\nCrit!\n";
                    this->stressHealing(5);
                    std::cout << this->getName() << "'s stress decreased 5.\n";
                }
                team[target_pos]->takeDamage(damage);
                std::cout << "\n" << this->name << " damage " << team[target_pos]->getName() << " " << std::to_string(damage) << "\n";
                // if (randomFunc::get_persent_bool(140 - team[target_pos].getStun())) {
                //     buff_and_effect::stun stun(team[target_pos]);
                //     team[target_pos].takeBuff(stun);
                //     std::cout << team[target_pos].getName() << " get a stun buff " << stun.samllInfo() << "\n";
                // }
            }  
        }
    }

    Bounty_Hunter::Bounty_Hunter(std::string hero_name, unsigned position_inteam) {
        this->skill1_targets = hero_settings::Bounty_Hunter::skill::Finish_Him::Target;
        this->skill2_targets = hero_settings::Bounty_Hunter::skill::Collect_Bounty::Target;
        this->name = hero_name;
        this->description = hero_settings::Bounty_Hunter::description;
        this->is_dead = false;
        this->is_dying = false;
        this->maxHealth = hero_settings::Bounty_Hunter::maxHealth;
        this->health = this->maxHealth;
        this->min_attack = hero_settings::Bounty_Hunter::min_attack;
        this->max_attack = hero_settings::Bounty_Hunter::max_attack;
        this->speed = hero_settings::Bounty_Hunter::speed;
        this->round_speed = this->speed;
        this->position_inteam = position_inteam;
        this->stress = 0;
        this->round_finsh = false;
        this->skill1_description = hero_settings::Bounty_Hunter::skill::Finish_Him::description;
        this->skill2_description = hero_settings::Bounty_Hunter::skill::Collect_Bounty::description;
        this->skill1_name = hero_settings::Bounty_Hunter::skill::Finish_Him::name;
        this->skill2_name = hero_settings::Bounty_Hunter::skill::Collect_Bounty::name;
        this->crit = hero_settings::Bounty_Hunter::crit;
        this->blight = hero_settings::Bounty_Hunter::blight;
        this->bleed = hero_settings::Bounty_Hunter::bleed;
        this->stun = hero_settings::Bounty_Hunter::stun;
        this->deathBlow = hero_settings::Bounty_Hunter::deathBlow;
        this->trap = hero_settings::Bounty_Hunter::trap;
        this->dodge = hero_settings::Bounty_Hunter::dodge;
    }

    Bounty_Hunter::~Bounty_Hunter() {
        
    }

    heros::Bounty_Hunter::Bounty_Hunter(const Bounty_Hunter& other) :
        Ahero(other) 
    {}

    heros::Bounty_Hunter& heros::Bounty_Hunter::operator=(const Bounty_Hunter& other) {
        if (this != &other) {
            Ahero::operator=(other);
        }
        return *this;
    }

    void Bounty_Hunter::skill1(std::vector<ICharacter*>& team, std::vector<ICharacter*>& other_team, unsigned target_pos) {
        if (target_pos >= team.size()) {
            std::cout << "The air in position " << std::to_string(target_pos + 1) << " get hurt...\n";
        } else {
            std::cout << this->name << " use " << this->skill1_name << "\n";
            unsigned damage = randomFunc::get_Random_Num(this->min_attack, this->max_attack) * hero_settings::Bounty_Hunter::skill::Finish_Him::damage_times;
            if (randomFunc::get_persent_bool(this->crit))
            {
                damage *= 1.5;
                std::cout << "\nCrit!\n";
                this->stressHealing(5);
                std::cout << this->getName() << "'s stress decreased 5.\n";
            }
            
            for (auto* obj : team) {
                if (auto* e = dynamic_cast<Aenemy*>(obj)) {
                    e->takeDamage(damage);
                    std::cout << "\n" << this->name << " damage " << e->getName() << " " << std::to_string(damage) << "\n";
                }
                // if (randomFunc::get_persent_bool(140 - team[target_pos].getBleed())) {
                //     buff_and_effect::bleed bleed(1, 1, team[target_pos]);
                //     team[target_pos].takeBuff(bleed);
                //     std::cout << team[target_pos].getName() << " get a bled buff " << bleed.samllInfo() << "\n";
                // }
            }
        }
    }
    
    void Bounty_Hunter::skill2(std::vector<ICharacter*>& team, std::vector<ICharacter*>& other_team, unsigned target_pos) {
        if (target_pos >= team.size()) {
            std::cout << "The air in position " << std::to_string(target_pos + 1) << " get hurt...\n";
        } else {
            std::cout << this->name << " use " << this->skill2_name << " to " << team[target_pos]->getName();
            if (target_pos > team.size() - 1 || randomFunc::get_persent_bool(team[target_pos]->getDodge())) {
                std::cout << "\nMiss!\n";
            } else {
                unsigned damage = randomFunc::get_Random_Num(this->min_attack, this->max_attack) * hero_settings::Bounty_Hunter::skill::Collect_Bounty::damage_times;
                if (randomFunc::get_persent_bool(this->crit + hero_settings::Bounty_Hunter::skill::Collect_Bounty::self_crit))
                {
                    damage *= 1.5;
                    std::cout << "\nCrit!\n";
                    this->stressHealing(5);
                    std::cout << this->getName() << "'s stress decreased 5.\n";
                }
                team[target_pos]->takeDamage(damage);
                std::cout << "\n" << this->name << " damage " << team[target_pos]->getName() << " " << std::to_string(damage) << "\n";
                // if (randomFunc::get_persent_bool(140 - team[target_pos].getStun())) {
                //     buff_and_effect::stun stun(team[target_pos]);
                //     team[target_pos].takeBuff(stun);
                //     std::cout << team[target_pos].getName() << " get a stun buff " << stun.samllInfo() << "\n";
                // }
            }  
        }
    }

    Leper::Leper(std::string hero_name, unsigned position_inteam) {
        this->skill1_targets = std::vector<unsigned> {position_inteam};
        this->skill2_targets = hero_settings::Leper::skill::Chop::Target;
        this->name = hero_name;
        this->description = hero_settings::Leper::description;
        this->is_dead = false;
        this->is_dying = false;
        this->maxHealth = hero_settings::Leper::maxHealth;
        this->health = this->maxHealth;
        this->min_attack = hero_settings::Leper::min_attack;
        this->max_attack = hero_settings::Leper::max_attack;
        this->speed = hero_settings::Leper::speed;
        this->round_speed = this->speed;
        this->position_inteam = position_inteam;
        this->stress = 0;
        this->round_finsh = false;
        this->skill1_description = hero_settings::Leper::skill::Solemnity::description;
        this->skill2_description = hero_settings::Leper::skill::Chop::description;
        this->skill1_name = hero_settings::Leper::skill::Solemnity::name;
        this->skill2_name = hero_settings::Leper::skill::Chop::name;
        this->crit = hero_settings::Leper::crit;
        this->blight = hero_settings::Leper::blight;
        this->bleed = hero_settings::Leper::bleed;
        this->stun = hero_settings::Leper::stun;
        this->deathBlow = hero_settings::Leper::deathBlow;
        this->trap = hero_settings::Leper::trap;
        this->dodge = hero_settings::Leper::dodge;
    }

    Leper::~Leper() {
        
    }

    heros::Leper::Leper(const Leper& other) :
        Ahero(other) 
    {}

    heros::Leper& heros::Leper::operator=(const Leper& other) {
        if (this != &other) {
            Ahero::operator=(other);
        }
        return *this;
    }

    void Leper::skill1(std::vector<ICharacter*>& team, std::vector<ICharacter*>& other_team, unsigned target_pos) {
        if (target_pos >= other_team.size()) {
            std::cout << "The air in position " << std::to_string(target_pos + 1) << " get hurt...\n";
        } else {
            std::cout << this->name << " use " << this->skill1_name << "\n";
            unsigned damage = hero_settings::Leper::skill::Solemnity::Health_healing;
            unsigned healing = hero_settings::Leper::skill::Solemnity::stress_healing;
            if (randomFunc::get_persent_bool(this->crit))
            {
                damage *= 1.5;
                std::cout << "\nCrit!\n";
                this->stressHealing(5);
                std::cout << this->getName() << "'s stress decreased 5.\n";
            }
            
            if (auto* h = dynamic_cast<Ahero*>(other_team[target_pos])) {
                h->healing(damage);
                h->stressHealing(healing);
                std::cout << "\n" << this->name << " healing " << other_team[target_pos]->getName() << " " << std::to_string(damage) << "\n";
                std::cout << "\n" << this->name << " reduce " << other_team[target_pos]->getName() << "'s stress " << std::to_string(healing) << "\n";
            }
    
                // if (randomFunc::get_persent_bool(140 - team[target_pos].getBleed())) {
                //     buff_and_effect::bleed bleed(1, 1, team[target_pos]);
                //     team[target_pos].takeBuff(bleed);
                //     std::cout << team[target_pos].getName() << " get a bled buff " << bleed.samllInfo() << "\n";
                // }
            
        }
    }
    
    void Leper::skill2(std::vector<ICharacter*>& team, std::vector<ICharacter*>& other_team, unsigned target_pos) {
        if (target_pos >= team.size()) {
            std::cout << "The air in position " << std::to_string(target_pos + 1) << " get hurt...\n";
        } else {
            std::cout << this->name << " use " << this->skill2_name << " to " << team[target_pos]->getName();
            if (target_pos > team.size() - 1 || randomFunc::get_persent_bool(team[target_pos]->getDodge())) {
                std::cout << "\nMiss!\n";
            } else {
                unsigned damage = randomFunc::get_Random_Num(this->min_attack, this->max_attack) * hero_settings::Leper::skill::Chop::damage_times;
                if (randomFunc::get_persent_bool(this->crit + hero_settings::Leper::skill::Chop::self_crit))
                {
                    damage *= 1.5;
                    std::cout << "\nCrit!\n";
                    this->stressHealing(5);
                    std::cout << this->getName() << "'s stress decreased 5.\n";
                }
                team[target_pos]->takeDamage(damage);
                std::cout << "\n" << this->name << " damage " << team[target_pos]->getName() << " " << std::to_string(damage) << "\n";
                // if (randomFunc::get_persent_bool(140 - team[target_pos].getStun())) {
                //     buff_and_effect::stun stun(team[target_pos]);
                //     team[target_pos].takeBuff(stun);
                //     std::cout << team[target_pos].getName() << " get a stun buff " << stun.samllInfo() << "\n";
                // }
            }  
        }
    }

    Vestal::Vestal(std::string hero_name, unsigned position_inteam) {
        this->skill1_targets = hero_settings::Vestal::skill::Divine_Grace::Target;
        this->skill2_targets = hero_settings::Vestal::skill::Judgement::Target;
        this->name = hero_name;
        this->description = hero_settings::Vestal::description;
        this->is_dead = false;
        this->is_dying = false;
        this->maxHealth = hero_settings::Vestal::maxHealth;
        this->health = this->maxHealth;
        this->min_attack = hero_settings::Vestal::min_attack;
        this->max_attack = hero_settings::Vestal::max_attack;
        this->speed = hero_settings::Vestal::speed;
        this->round_speed = this->speed;
        this->position_inteam = position_inteam;
        this->stress = 0;
        this->round_finsh = false;
        this->skill1_description = hero_settings::Vestal::skill::Divine_Grace::description;
        this->skill2_description = hero_settings::Vestal::skill::Judgement::description;
        this->skill1_name = hero_settings::Vestal::skill::Divine_Grace::name;
        this->skill2_name = hero_settings::Vestal::skill::Judgement::name;
        this->crit = hero_settings::Vestal::crit;
        this->blight = hero_settings::Vestal::blight;
        this->bleed = hero_settings::Vestal::bleed;
        this->stun = hero_settings::Vestal::stun;
        this->deathBlow = hero_settings::Vestal::deathBlow;
        this->trap = hero_settings::Vestal::trap;
        this->dodge = hero_settings::Vestal::dodge;
    }

    Vestal::~Vestal() {
        
    }

    heros::Vestal::Vestal(const Vestal& other) :
        Ahero(other) 
    {}

    heros::Vestal& heros::Vestal::operator=(const Vestal& other) {
        if (this != &other) {
            Ahero::operator=(other);
        }
        return *this;
    }

    void Vestal::skill1(std::vector<ICharacter*>& team, std::vector<ICharacter*>& other_team, unsigned target_pos) {
        if (target_pos >= other_team.size()) {
            std::cout << "The air in position " << std::to_string(target_pos + 1) << " get hurt...\n";
        } else {
            std::cout << this->name << " use " << this->skill1_name << " to " << other_team[target_pos]->getName();
            unsigned damage = hero_settings::Vestal::skill::Divine_Grace::Health_healing;
            if (randomFunc::get_persent_bool(this->crit))
            {
                damage *= 1.5;
                std::cout << "\nCrit!\n";
                this->stressHealing(5);
                std::cout << this->getName() << "'s stress decreased 5.\n";
            }
            if (auto* h = dynamic_cast<Ahero*>(other_team[target_pos])) {
                h->healing(damage);
                std::cout << "\n" << this->name << " healing " << other_team[target_pos]->getName() << " " << std::to_string(damage) << "\n";
            }
                // if (randomFunc::get_persent_bool(140 - team[target_pos].getBleed())) {
                //     buff_and_effect::bleed bleed(1, 1, team[target_pos]);
                //     team[target_pos].takeBuff(bleed);
                //     std::cout << team[target_pos].getName() << " get a bled buff " << bleed.samllInfo() << "\n";
                // }
            
        }
    }

    void Vestal::skill2(std::vector<ICharacter*>& team, std::vector<ICharacter*>& other_team, unsigned target_pos) {
        if (target_pos >= team.size()) {
            std::cout << "The air in position " << std::to_string(target_pos + 1) << " get hurt...\n";
        } else {
            std::cout << this->name << " use " << this->skill2_name << " to " << team[target_pos]->getName();
            if (target_pos > team.size() - 1 || randomFunc::get_persent_bool(team[target_pos]->getDodge())) {
                std::cout << "\nMiss!\n";
            } else {
                unsigned damage = randomFunc::get_Random_Num(this->min_attack, this->max_attack) * hero_settings::Vestal::skill::Judgement::damage_times;
                if (randomFunc::get_persent_bool(this->crit + hero_settings::Vestal::skill::Judgement::self_crit))
                {
                    damage *= 1.5;
                    std::cout << "\nCrit!\n";
                    this->stressHealing(5);
                    std::cout << this->getName() << "'s stress decreased 5.\n";
                }
                team[target_pos]->takeDamage(damage);
                other_team[this->position_inteam]->healing(hero_settings::Vestal::skill::Judgement::Health_healing);
                std::cout << "\n" << this->name << " healing " << this->name << " " << std::to_string(hero_settings::Vestal::skill::Judgement::Health_healing);
                std::cout << "\n" << this->name << " damage " << team[target_pos]->getName() << " " << std::to_string(damage) << "\n";
                // if (randomFunc::get_persent_bool(140 - team[target_pos].getStun())) {
                //     buff_and_effect::stun stun(team[target_pos]);
                //     team[target_pos].takeBuff(stun);
                //     std::cout << team[target_pos].getName() << " get a stun buff " << stun.samllInfo() << "\n";
                // }
            }  
        }
    }

    Plague_Doctor::Plague_Doctor(std::string hero_name, unsigned position_inteam) {
        this->skill1_targets = hero_settings::Plague_Doctor::skill::Battlefield_Medicine::Target;
        this->skill2_targets = hero_settings::Plague_Doctor::skill::surgery::Target;
        this->name = hero_name;
        this->description = hero_settings::Plague_Doctor::description;
        this->is_dead = false;
        this->is_dying = false;
        this->maxHealth = hero_settings::Plague_Doctor::maxHealth;
        this->health = this->maxHealth;
        this->min_attack = hero_settings::Plague_Doctor::min_attack;
        this->max_attack = hero_settings::Plague_Doctor::max_attack;
        this->speed = hero_settings::Plague_Doctor::speed;
        this->round_speed = this->speed;
        this->position_inteam = position_inteam;
        this->stress = 0;
        this->round_finsh = false;
        this->skill1_description = hero_settings::Plague_Doctor::skill::Battlefield_Medicine::description;
        this->skill2_description = hero_settings::Plague_Doctor::skill::surgery::description;
        this->skill1_name = hero_settings::Plague_Doctor::skill::Battlefield_Medicine::name;
        this->skill2_name = hero_settings::Plague_Doctor::skill::surgery::name;
        this->crit = hero_settings::Plague_Doctor::crit;
        this->blight = hero_settings::Plague_Doctor::blight;
        this->bleed = hero_settings::Plague_Doctor::bleed;
        this->stun = hero_settings::Plague_Doctor::stun;
        this->deathBlow = hero_settings::Plague_Doctor::deathBlow;
        this->trap = hero_settings::Plague_Doctor::trap;
        this->dodge = hero_settings::Plague_Doctor::dodge;
    }

    Plague_Doctor::~Plague_Doctor() {
        
    }

    heros::Plague_Doctor::Plague_Doctor(const Plague_Doctor& other) :
        Ahero(other) 
    {}

    heros::Plague_Doctor& heros::Plague_Doctor::operator=(const Plague_Doctor& other) {
        if (this != &other) {
            Ahero::operator=(other);
        }
        return *this;
    }

    void Plague_Doctor::skill1(std::vector<ICharacter*>& team, std::vector<ICharacter*>& other_team, unsigned target_pos) {
        if (target_pos >= other_team.size()) {
            std::cout << "The air in position " << std::to_string(target_pos + 1) << " get hurt...\n";
        } else {
            std::cout << this->name << " use " << this->skill1_name << " to " << other_team[target_pos]->getName();
            unsigned damage = hero_settings::Plague_Doctor::skill::Battlefield_Medicine::Health_healing;
            if (randomFunc::get_persent_bool(this->crit))
            {
                damage *= 1.5;
                std::cout << "\nCrit!\n";
                this->stressHealing(5);
                std::cout << this->getName() << "'s stress decreased 5.\n";
            }
            if (auto* h = dynamic_cast<Ahero*>(other_team[target_pos])) {
                h->healing(damage);
                std::cout << "\n" << this->name << " healing " << other_team[target_pos]->getName() << " " << std::to_string(damage) << "\n";
            }
                // if (randomFunc::get_persent_bool(140 - team[target_pos].getBleed())) {
                //     buff_and_effect::bleed bleed(1, 1, team[target_pos]);
                //     team[target_pos].takeBuff(bleed);
                //     std::cout << team[target_pos].getName() << " get a bled buff " << bleed.samllInfo() << "\n";
                // }
            
        }
    }

    void Plague_Doctor::skill2(std::vector<ICharacter*>& team, std::vector<ICharacter*>& other_team, unsigned target_pos) {
        if (target_pos >= team.size()) {
            std::cout << "The air in position " << std::to_string(target_pos + 1) << " get hurt...\n";
        } else {
            std::cout << this->name << " use " << this->skill2_name << " to " << team[target_pos]->getName();
            if (target_pos > team.size() - 1 || randomFunc::get_persent_bool(team[target_pos]->getDodge())) {
                std::cout << "\nMiss!\n";
            } else {
                unsigned damage = randomFunc::get_Random_Num(this->min_attack, this->max_attack) * hero_settings::Plague_Doctor::skill::surgery::damage_times;
                if (randomFunc::get_persent_bool(this->crit + hero_settings::Plague_Doctor::skill::surgery::self_crit))
                {
                    damage *= 1.5;
                    std::cout << "\nCrit!\n";
                    this->stressHealing(5);
                    std::cout << this->getName() << "'s stress decreased 5.\n";
                }
                team[target_pos]->takeDamage(damage);
                std::cout << "\n" << this->name << " damage " << team[target_pos]->getName() << " " << std::to_string(damage) << "\n";
                // if (randomFunc::get_persent_bool(140 - team[target_pos].getStun())) {
                //     buff_and_effect::stun stun(team[target_pos]);
                //     team[target_pos].takeBuff(stun);
                //     std::cout << team[target_pos].getName() << " get a stun buff " << stun.samllInfo() << "\n";
                // }
            }  
        }
    }
} // namespace heros
